
/*
 XMail OSAX -- Copyright (C) 2004, 2005, 2006, 2007 Jean-Baptiste LE STANG osax@lestang.org
 
	
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.
 
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 */

#include "XMail-tools.h"
#include "pcrecpp.h"
static  XMailEncoder * gCurrentEncoder = NULL;

void XMailSetEncoder(XMailEncoder * enc){
    gCurrentEncoder = enc;
}

XMailEncoder * XMailGetEncoder(){
    return gCurrentEncoder;
}

OSStatus XMailFindPasswordInKeychain(char * keychainName, char * smtp, char * username, int port, char ** password){
    SecKeychainRef keychain = NULL;
    
    UInt32 passwordLength = 0;
    char * passwordData = NULL;
    passwordLength = 0;
    OSStatus err = SecKeychainCopyDefault (&keychain);
    if (err == noErr){
        err = SecKeychainFindInternetPassword(keychain,strlen(smtp),smtp,0,NULL,strlen(username),username,0,NULL,port,kSecProtocolTypeSMTP, kSecAuthenticationTypeDefault,&passwordLength,(void **)&passwordData,NULL);
        if (err == noErr){
            *password = (char *)malloc((passwordLength+1) * sizeof(char));
            memset(*password,0,(passwordLength+1));
            memcpy(*password,passwordData,passwordLength);
        }
    }
    return noErr;
}

OSStatus	XMailConvertText(char * inputText,char ** outputText, char * inputEncodingName, char * outputEncodingName)
{	 
    OSStatus		err;
    TextEncoding	fromEncoding;
    TextEncoding	toEncoding;
    ByteCount		inputTextSize;
    ByteCount		outputTextSize;
    
    ByteCount	actualInputLength = 0;	
	ByteCount	otCurrentTextSize = 0;	
    ByteCount	flushLen = 0;
    
    TECObjectRef	encodingConverter = nil;
    
    if (inputText == NULL || strlen(inputText) == 0){
        outputTextSize = 1;
        *outputText = (char *) malloc(sizeof(char)*outputTextSize);
        memset( *outputText,0,outputTextSize);
        return noErr;
    }
    
    
    Str255		psInputEncodingName;
    Str255		psOutputEncodingName;
    
    psInputEncodingName[0]=strlen(inputEncodingName);
    memcpy(psInputEncodingName+1,(unsigned char *)inputEncodingName,strlen(inputEncodingName));
    psOutputEncodingName[0]=strlen(outputEncodingName);
    memcpy(psOutputEncodingName+1,(unsigned char *)outputEncodingName,strlen(outputEncodingName));
    /* check they are not the same, in wich case, do a blind copy of the data to outputText*/
    err = TECGetTextEncodingFromInternetName(&fromEncoding,psInputEncodingName);
    err = TECGetTextEncodingFromInternetName(&toEncoding,psOutputEncodingName);
    
    inputTextSize = strlen(inputText);
    outputTextSize = 6 * inputTextSize;
 	err = TECCreateConverter(&encodingConverter,fromEncoding,toEncoding);
    
    /* worst case scenario */
    
    *outputText = (char *) malloc(sizeof(char)*outputTextSize);
    memset( *outputText,0,outputTextSize);
    
	err = TECConvertText(encodingConverter,(UInt8 *)inputText,inputTextSize,&actualInputLength,(UInt8 *)*outputText,outputTextSize,&otCurrentTextSize);
	err = TECFlushText(encodingConverter,(UInt8 *)*outputText + otCurrentTextSize,outputTextSize - otCurrentTextSize,&flushLen);
	otCurrentTextSize += flushLen;
	
	if ( encodingConverter ) {
		TECDisposeConverter(encodingConverter);
	}
	return err;
}
/*XMailEncoder*/
char * XMailEncodeEmailAddress(char * rawemail,char ** name, char ** email){
    char * encoded_name = NULL;
    char * encoded = NULL;
    int final_size = 0;
    matchEmailAndName(rawemail,name,email);
    if (name != NULL && email != NULL && *name != NULL && *email != NULL){
        char* tmp = NULL;
        XMailConvertText(*name,&tmp,"UTF-8",gCurrentEncoder->encoderName);
        encoded_name= gCurrentEncoder->encoderFunction(tmp);
        final_size = (strlen(encoded_name)+strlen(*email)+3);
        encoded = (char *)malloc(sizeof(char)*(final_size+1));
        memset(encoded,0,final_size+1);
        sprintf(encoded,"%s <%s>",encoded_name,*email);
    } else if (email != NULL && *email != NULL) {
        final_size = (strlen(*email));
        encoded = (char *)malloc(sizeof(char)*(final_size+1));
        memset(encoded,0,final_size+1);
        sprintf(encoded,"%s",*email);
    } else {
        encoded = NULL;
    }
    return encoded;
}

OSStatus XMailMakeErrorReply(AppleEvent *theReply, const OSErr theErrorCode, char *theMessage) {
	OSErr err = noErr;
	err = AEPutParamPtr(theReply, keyErrorString, typeChar, theMessage, strlen(theMessage));
	return theErrorCode;
}


OSStatus XMailGetDescString(const AEDesc *theDesc, char **  theString) {
	OSStatus err = paramErr;
	if(theDesc != NULL) {
		err = AEDescToCharPtr(*theDesc,theString);
	}
	return err;
}


OSStatus XMailGetTextParamAsString(const AppleEvent *theEvent, const AEKeyword theKeyword, char ** theField) {
	OSErr err = paramErr;
	AEDesc desc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, theKeyword, typeText, &desc);
	if(err == noErr) {
		err = AEDescToCharPtr(desc,theField);
		AEDisposeDesc(&desc);
	}
	return err;
}

OSStatus XMailGetUnicodeParamAsString(const AppleEvent *theEvent, const AEKeyword theKeyword, const TextEncoding toEncoding, char ** theField) {
#pragma unused(toEncoding)
    
	OSStatus err = paramErr;
	AEDesc desc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, theKeyword, typeWildCard, &desc);
	if(err == noErr) {
		err = AEDescToUTF8(desc,theField);
		AEDisposeDesc(&desc);
	}
	return err;
}

OSStatus XMailGetListItemAsString(const AEDescList *theList, const DescType theType, const SInt32 theIndex, char ** theField) {	
	OSErr err = noErr;
	AEKeyword keyword;
	AEDesc desc = {typeNull, NULL };
	err = AEGetNthDesc(theList, theIndex, theType, &keyword, &desc);
	if(err == noErr) {
		err = XMailGetDescString(&desc, theField);
		AEDisposeDesc(&desc);
	}
	return err;
}


OSStatus XMailGetParamListItemAsString(const AppleEvent *theEvent, const AEKeyword theKeyword, const DescType theType, const SInt32 theIndex,char *theField) {
	OSErr err = noErr;
	AEDescList ldesc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, theKeyword, typeAEList, &ldesc);
	if(err == noErr) {
		err = XMailGetListItemAsString(&ldesc, theType, theIndex, &theField);
		AEDisposeDesc(&ldesc);
	}
	return err;
}

OSStatus XMailGenericEmail(const AppleEvent * theEvent, const AEKeyword theKeyword, char ** dest,char **destEsc){
	OSErr err = noErr;
	AEDesc desc = {typeNull, NULL};
    char * rawemail = NULL;
    char * name = NULL;
	err = AEGetParamDesc(theEvent, theKeyword, typeWildCard, &desc);
	if(err == noErr){
        err = AEDescToUTF8(desc,&rawemail);
		if(err == noErr){
            *destEsc = XMailEncodeEmailAddress(rawemail,&name,dest);
			if (*destEsc == NULL){
				err =+ -1;
			}
            if (name != NULL) FREE(name);
			if (rawemail != NULL) FREE(rawemail);
		}
		AEDisposeDesc(&desc);
	}
    return err;
}

OSStatus	XMailDoReplyTo(const AppleEvent * theEvent, mail_t * mail){
	return XMailGenericEmail(theEvent,kMailReplyTo,&(mail->returnAddress),&(mail->returnAddressEsc));
}

OSStatus	XMailDoErrorsTo(const AppleEvent * theEvent, mail_t * mail){
	return XMailGenericEmail(theEvent,kMailReturnErrors,&(mail->errorAddress),&(mail->errorAddressEsc));
}	

OSStatus	XMailDoFrom(const AppleEvent * theEvent, mail_t * mail){
	return XMailGenericEmail(theEvent,kMailSendFrom,&(mail->from),&(mail->fromEsc));
}

OSStatus	XMailDoLogin(const AppleEvent * theEvent, mail_t * mail){
	OSErr err = noErr;
	AEDesc desc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, kMailLogin, typeWildCard, &desc);
	if(err == noErr){
		err = AEDescToUTF8(desc,&(mail->user));
		AEDisposeDesc(&desc);
	}
	return err;
}

OSStatus	XMailDoPassword(const AppleEvent * theEvent, mail_t * mail){
	OSErr err = noErr;
	AEDesc desc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, kMailPassword, typeWildCard, &desc);
	if(err == noErr){
		err = AEDescToUTF8(desc,&(mail->password));
		AEDisposeDesc(&desc);
	}
	return err;
}


OSStatus	XMailDoRawBody(const AppleEvent * theEvent, mail_t * mail, char * inputEncoding){
	OSErr err = noErr;
	AEDesc desc = {typeNull, NULL};
    char * inputData = NULL;
	err = AEGetParamDesc(theEvent, kMailSendBody, typeWildCard, &desc);
	if(err == noErr){
        err = AEDescToUTF8(desc,&inputData);
        XMailConvertText(inputData,&(mail->body),"utf-8",inputEncoding);
		AEDisposeDesc(&desc);
		quotedPrintableEncode(mail->body,&(mail->body_encoded),0);
	}
    if (inputData != NULL) free(inputData);
	return err;
}


OSStatus	XMailDoDate(const AppleEvent * theEvent, mail_t * mail){
	OSErr err = noErr;
	AEDesc desc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, 'udat', typeWildCard, &desc);
	if(err == noErr){
		err = AEDescToUTF8(desc,&(mail->usingDate));
        if (err == errAECoercionFail){ /* est-ce une date AppleScript ?*/
            SInt64 date = 0;
            DescType typeCode = '0000';
            Size actualSize = 0;
            err = AEGetParamPtr (theEvent,'udat','ldt ',&typeCode,&date,sizeof(date),&actualSize);
            if (err == noErr && date !=0){
                CFAbsoluteTime oCFTime;
                UCConvertLongDateTimeToCFAbsoluteTime(date,&oCFTime);
                CFLocaleRef locale = CFLocaleCreate(NULL,CFSTR("en"));
                CFDateFormatterRef dateFormater = CFDateFormatterCreate(NULL,locale, kCFDateFormatterNoStyle, kCFDateFormatterNoStyle);
                CFDateFormatterSetFormat(dateFormater,CFSTR("'Date:' d MMM yy hh:mm:ss Z"));
                CFStringRef fdate = CFDateFormatterCreateStringWithAbsoluteTime(NULL,dateFormater,oCFTime);
                mail->usingDate = (char *) malloc(sizeof(char)*1024);
                CFStringGetCString(fdate,mail->usingDate,1024,kCFStringEncodingASCII);
                CFRelease(locale);
                CFRelease(dateFormater);
                CFRelease(fdate);
            }
            
        }
        err = AEDisposeDesc(&desc);
	}
return err;
}

OSStatus	XMailDoBody(const AppleEvent * theEvent, mail_t * mail,char * inputEncoding,char * outputEncoding){
	OSErr err = noErr;
	AEDesc desc = {typeNull, NULL};
    char * tmp = NULL;
    
	err = AEGetParamDesc(theEvent, kMailSendBody, typeWildCard, &desc);
	if(err == noErr){
		err = AEDescToUTF8(desc,&tmp);
        XMailConvertText(tmp,&(mail->body),inputEncoding,outputEncoding);
		AEDisposeDesc(&desc);
		quotedPrintableEncode(mail->body,&(mail->body_encoded),0);
	}
	return err;
}


OSStatus	XMailDoSubject(const AppleEvent * theEvent, mail_t * mail,char * inputEncoding){
	OSErr err = noErr;
	AEDesc desc = {typeNull, NULL};
    char * tmp = NULL;
	err = AEGetParamDesc(theEvent, kMailSendSubject, typeWildCard, &desc);
	if(err == noErr){
		err = AEDescToUTF8(desc,&tmp);
        XMailConvertText(tmp,&(mail->subject),inputEncoding,gCurrentEncoder->encoderName);
		AEDisposeDesc(&desc);
		mail->subject_encoded = mail->encoder->encoderSplitterFunction(mail->subject);
	}
	return err;
}

OSStatus	XMailDoServer(const AppleEvent * theEvent, mail_t * mail){
	OSErr err = noErr;
	AEDesc desc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, kMailSendSMTPServer, typeWildCard, &desc);
	if(err == noErr){
		err = AEDescToUTF8(desc,&(mail->server));
		AEDisposeDesc(&desc);
	} else {
		mail->server = (char *)malloc(sizeof(char)*strlen("localhost"));
		sprintf(mail->server,"%s","localhost");
	}
	return err;
}

OSStatus XMailDoRecipients(const AppleEvent *theEvent, const AEKeyword theKeyword, mail_t * mail,recipient_t theRecipientKind) {
	OSErr err = noErr;
	AEDescList ldesc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, theKeyword, typeAEList, &ldesc);
	if(err == noErr) {
		SInt32 lcount = 0;
		err = AECountItems(&ldesc, &lcount);
		if(err == noErr) {
			SInt32 index = 0;
			for(index = 1; index <= lcount; index++){
				AEKeyword keyword;
				AEDesc desc = {typeNull, NULL};
				err = AEGetNthDesc(&ldesc, index, typeWildCard, &keyword, &desc);
				if(err == noErr){
					char * str = NULL;
					err = AEDescToUTF8(desc,&str);
					if(err == noErr) {
						char * email = NULL;
                        char * encoded = NULL;
                        encoded = XMailEncodeEmailAddress(str,&encoded,&email);
						if (encoded == NULL) {
							err += -1;
						}
                        mail_addRecipient(mail,theRecipientKind,email,encoded);
						if (str != NULL) free(str);
						AEDisposeDesc(&desc);
					}
				}
			}
		}
		AEDisposeDesc(&ldesc);
	}
    return err;
}



OSStatus XMailDoAttachments(const AppleEvent *theEvent,mail_t * mail) {
	OSStatus err = noErr;
	AEDescList ldesc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, kMailSendAttachment, typeAEList, &ldesc);
	if(err == noErr) {
		SInt32 lcount = 0;
		unsigned int i = 0;
		err = AECountItems(&ldesc, &lcount);
		for(i = 1 ; i <= lcount ; i++) {
			FSRef fsref;
			UInt8 * posix_path = (UInt8 *)malloc(sizeof(UInt8)*kXMailMaxPathLength);
			AEKeyword keyword = '0000';
			DescType type='0000';
			SInt32 out_size = 0;
			err = AEGetNthPtr(&ldesc, i, typeFSRef, &keyword, &type, &fsref, sizeof(FSRef), &out_size);
			if(err == noErr) {
				err = FSRefMakePath(&fsref, posix_path, kXMailMaxPathLength);
				if(err == noErr) {
					mail_addFile(mail,(char *)posix_path);
				}
			}
		}
		AEDisposeDesc(&ldesc);
	}
	return err;
}

OSStatus XMailDoGetPort(const AppleEvent * theEvent,  mail_t * mail){
	OSStatus err = noErr;
	AEDesc desc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, kMailPort, typeLongInteger, &desc);
	if(err == noErr) {
		err = AEGetDescData(&desc, (void *)&(mail->port) , sizeof(long)); 
		AEDisposeDesc(&desc);
	}
	return err;
}

OSStatus XMailDoGetTimeout(const AppleEvent * theEvent,  mail_t * mail){
	OSStatus err = noErr;
	AEDesc desc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, kMailTimeout, typeLongInteger, &desc);
	if(err == noErr) {
		err = AEGetDescData(&desc, (void *)&(mail->timeout), sizeof(long)); 
		AEDisposeDesc(&desc);
	}
	return err;
}

OSStatus XMailDoPriority(const AppleEvent *theEvent,mail_t * mail) {
	OSStatus err = noErr;
	AEDesc desc = {typeNull, NULL};
	int priority = 3;
	mail->priority = priority;
	err = AEGetParamDesc(theEvent, kMailPriority, typeInteger, &desc);
	if(err == noErr) {
		err = AEGetDescData(&desc, (void *)&priority, sizeof(int)); 
		if(err == noErr) {
			if ((priority>5)||(priority<0)) priority = 3;
			mail->priority = priority;
		}
		AEDisposeDesc(&desc);
	}
	return err;
}

OSStatus XMailDoGetSSL(const AppleEvent * theEvent,mail_t * mail){
	DescType	actualType = '0000';
    Size  		actualSize = 0;
	AEKeyword   theKeyWord = '0000';
	OSErr		err = noErr;
	Boolean theBoolean = false;
	
	mail->security = NO_SSL;
	mail->check_type = VERIFY_NONE;
	
	err = AEGetParamPtr(theEvent, kMailSSL, typeBoolean,&actualType, (Ptr)&theBoolean,sizeof(Boolean), &actualSize);
	if (err != noErr) return err;
    if (theBoolean==1){
		mail->security = STARTTLS;
	} else {
		mail->security = NO_SSL;
	}
	
    err = AEGetParamPtr(theEvent, kMailSSLCheckType, typeEnumerated,&actualType, (Ptr)&theKeyWord,sizeof(AEKeyword), &actualSize);
	if (err != noErr) return err;
	if (theKeyWord == enumVerifyNone){
		mail->check_type = VERIFY_NONE;
	} else if (theKeyWord == enumVerifyPeer){
		mail->check_type = VERIFY_PEER;
	}
    return noErr;
}


OSStatus XMailDoGetSSLCertificates(const AppleEvent * theEvent,mail_t * mail){
	OSStatus	err = noErr;
	DescType	actualType = '0000',actualType2='0000';
    Size  		actualSize = 0,actualSize2 = 0;
	FSRef		fileCertRef;
	FSRef		dirCertRef;
	err = AEGetParamPtr(theEvent, kMailPEMFile, typeFSRef,&actualType, (Ptr)&fileCertRef,sizeof(fileCertRef), &actualSize);
	err = AEGetParamPtr(theEvent, kMailPEMDirectory, typeFSRef,&actualType2, (Ptr)&dirCertRef,sizeof(dirCertRef), &actualSize2);
	mail->certificatePath = (char *) malloc(sizeof(UInt8)*kXMailMaxPathLength);
	mail->certificateDirectory = (char *) malloc(sizeof(UInt8)*kXMailMaxPathLength);
	memset(mail->certificatePath,0,kXMailMaxPathLength);
	memset(mail->certificateDirectory,0,kXMailMaxPathLength);
	err = FSRefMakePath(&fileCertRef, (UInt8 *)mail->certificatePath, kXMailMaxPathLength);
	err = FSRefMakePath(&dirCertRef, (UInt8 *)mail->certificateDirectory, kXMailMaxPathLength);
	return err;
}


OSStatus XMailDoGetSASL(const AppleEvent * theEvent,mail_t * mail){
    DescType	actualType = '0000';
    Size  		actualSize = 0;
    AEKeyword   theKeyWord = '0000';
	OSErr		err = noErr;
    err = AEGetParamPtr(theEvent, kMailAuth, typeEnumerated,&actualType, (Ptr)&theKeyWord,sizeof(AEKeyword), &actualSize);
	
	if (err != noErr) return err;
	switch(theKeyWord){
		case enumPlain :mail->sasl = PLAIN;break;
		case enumLogin :mail->sasl = LOGIN;break;
		case enumCrammd5 :mail->sasl = CRAMMD5;break;
		case enumAnonymous : mail->sasl = ANONYMOUS;break;
		case enumAuto : mail->sasl = AUTO;break;
		case enumCramsha1 : mail->sasl = CRAMSHA1;break;
		case enumDigestmd5 : mail->sasl = DIGESTMD5;break;
		case enumPop3: mail->sasl = POP3;break;
		case enumAPop: mail->sasl = APOP;break;
		default : break;
	}
	return noErr;
}


OSStatus XMailDoExtraHeaders(const AppleEvent *theEvent,mail_t * mail) {
	OSStatus err = noErr;
	AEDescList ldesc = {typeNull,NULL};	
	err = AEGetParamDesc(theEvent, kMailXtraHeaders, typeAEList, &ldesc);
	if(err == noErr) {
		SInt32 lcount;
		unsigned int i = 0;
		err = AECountItems(&ldesc, &lcount);
		for(i = 1 ; i <= lcount ; i++) {
			AEDesc desc = {typeNull, NULL};
			AEKeyword keyword;
			char * name_str;
			char * value_str;
			err = AEGetNthDesc(&ldesc, i, typeAEList, &keyword, &desc);
			if(err == noErr) {
				err = XMailGetListItemAsString(&desc,typeWildCard, 1,&name_str);
				err = XMailGetListItemAsString(&desc,typeWildCard, 2,&value_str);
				mail_addExtraHeader(mail,name_str,value_str);				
			}
		}
	}
	(void) AEDisposeDesc(&ldesc);
	return err;
}


/*
 send mail to "toto <toto@jbook.local>" from "toto <toto@jbook.local>" body "ok" subject "ok" smtp server "localhost"
 */

int XMailGetTypeRecipientsCount(const AppleEvent * theEvent,AEKeyword type){
	SInt32 count = 0;
	OSErr err = noErr;
	AEDescList ldesc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, type, typeAEList, &ldesc);
	if (err == noErr){
		err = AECountItems(&ldesc, &count);
	}
	if (err ==noErr) AEDisposeDesc(&ldesc);
	return count;
}

int XMailGetRecipientsCount(const AppleEvent * theEvent){
	int res = 0;
	res +=XMailGetTypeRecipientsCount(theEvent,kMailSendCC);
	res +=XMailGetTypeRecipientsCount(theEvent,kMailSendBCC);
	res +=XMailGetTypeRecipientsCount(theEvent,kMailSendTo);
	return res;
}

OSStatus XMailGetEncoding(const AppleEvent * theEvent,AEKeyword key, char ** encodingName){
    OSErr err = noErr;
	AEDesc desc = {typeNull, NULL};
	err = AEGetParamDesc(theEvent, key, typeWildCard, &desc);
	if(err == noErr){
		err = AEDescToUTF8(desc,encodingName);
		AEDisposeDesc(&desc);
	} else {
		*encodingName = (char *)malloc(sizeof(char)*strlen("utf-8"));
		sprintf(*encodingName,"%s","utf-8");
	}
	return err;
}


OSStatus XMailGenerateKeyWordRcptsList(const AppleEvent * theEvent,AEKeyword key, mail_t * mail){
	OSErr err = noErr;
	AEDescList ldesc = {typeNull, NULL};
    SInt32 lcount = 0;
    SInt32 index = 0;
    AEKeyword keyword = '0000';
    AEDesc desc = {typeNull, NULL};
    char * email = NULL;
    char * str = NULL;
	err = AEGetParamDesc(theEvent, key, typeAEList, &ldesc);
	if(err == noErr) {
		err = AECountItems(&ldesc, &lcount);
		if(err == noErr) {
			for(index = 1; index <= lcount; index++) {
                str = NULL;
				err = AEGetNthDesc(&ldesc, index, typeWildCard, &keyword, &desc);
				if(err == noErr) {
					err = AEDescToUTF8(desc,&str);
					if(err == noErr) {
                        char * name = NULL;
						email = NULL;
						matchEmailAndName(str,&name,&email);
						if (email != NULL){
							dlist_ins_next(&(mail->gRecipients),dlist_tail(&mail->gRecipients), email);
                            if (name != NULL) FREE(name);
						} else {
							err = paramErr;
                            FREE(str);
                            AEDisposeDesc(&desc);
							AEDisposeDesc(&ldesc);
							return err;
						}
					}
					AEDisposeDesc(&desc);
					FREE(str);
				}
			}
		}
		AEDisposeDesc(&ldesc);
	}
	return err;
}

OSStatus XMailGenerateRcptsList(const AppleEvent * theEvent, mail_t * mail){
	OSErr err = noErr;
	XMailGenerateKeyWordRcptsList(theEvent,kMailSendTo, mail);
	XMailGenerateKeyWordRcptsList(theEvent,kMailSendCC, mail);
	XMailGenerateKeyWordRcptsList(theEvent,kMailSendBCC, mail);
	return err;
}
